#ifndef __HAL_GPIO_H__
#define __HAL_GPIO_H__

typedef void (*GPIOCallback)(void);

typedef enum
{
	GPIO_PIN_NOT_ASSIGNED = -1,

	GPIO_PIN_0 = 0,GPIO_PIN_1,  GPIO_PIN_2,  GPIO_PIN_3,  GPIO_PIN_4,  GPIO_PIN_5,  GPIO_PIN_6,  GPIO_PIN_7,

	GPIO_PIN_8,  GPIO_PIN_9,  GPIO_PIN_10, GPIO_PIN_11, GPIO_PIN_12, GPIO_PIN_13, GPIO_PIN_14, GPIO_PIN_15,
	GPIO_PIN_16, GPIO_PIN_17, GPIO_PIN_18, GPIO_PIN_19, GPIO_PIN_20, GPIO_PIN_21, GPIO_PIN_22, GPIO_PIN_23,
	GPIO_PIN_24, GPIO_PIN_25, GPIO_PIN_26, GPIO_PIN_27, GPIO_PIN_28, GPIO_PIN_29, GPIO_PIN_30, GPIO_PIN_31,
	GPIO_PIN_32, GPIO_PIN_33, GPIO_PIN_34, GPIO_PIN_35, GPIO_PIN_36, GPIO_PIN_37, GPIO_PIN_38, GPIO_PIN_39,

	GPIO_PIN_40, GPIO_PIN_41, GPIO_PIN_42, GPIO_PIN_43, GPIO_PIN_44, GPIO_PIN_45, GPIO_PIN_46, GPIO_PIN_47,
	GPIO_PIN_48, GPIO_PIN_49, GPIO_PIN_50, GPIO_PIN_51, GPIO_PIN_52, GPIO_PIN_53, GPIO_PIN_54, GPIO_PIN_55,
	GPIO_PIN_56, GPIO_PIN_57, GPIO_PIN_58, GPIO_PIN_59, GPIO_PIN_60, GPIO_PIN_61, GPIO_PIN_62, GPIO_PIN_63,

	GPIO_PIN_64, GPIO_PIN_65, GPIO_PIN_66, GPIO_PIN_67, GPIO_PIN_68, GPIO_PIN_69, GPIO_PIN_70, GPIO_PIN_71,
	GPIO_PIN_72, GPIO_PIN_73, GPIO_PIN_74, GPIO_PIN_75, GPIO_PIN_76, GPIO_PIN_77, GPIO_PIN_78, GPIO_PIN_79,
	GPIO_PIN_80, GPIO_PIN_81, GPIO_PIN_82, GPIO_PIN_83, GPIO_PIN_84, GPIO_PIN_85, GPIO_PIN_86, GPIO_PIN_87,
	GPIO_PIN_88, GPIO_PIN_89, GPIO_PIN_90, GPIO_PIN_91, GPIO_PIN_92, GPIO_PIN_93, GPIO_PIN_94, GPIO_PIN_95,

	GPIO_PIN_96,  GPIO_PIN_97,  GPIO_PIN_98,  GPIO_PIN_99,  GPIO_PIN_100, GPIO_PIN_101, GPIO_PIN_102, GPIO_PIN_103,
	GPIO_PIN_104, GPIO_PIN_105, GPIO_PIN_106, GPIO_PIN_107, GPIO_PIN_108, GPIO_PIN_109, GPIO_PIN_110, GPIO_PIN_111,
	GPIO_PIN_112, GPIO_PIN_113, GPIO_PIN_114, GPIO_PIN_115, GPIO_PIN_116, GPIO_PIN_117, GPIO_PIN_118, GPIO_PIN_119,
	GPIO_PIN_120, GPIO_PIN_121, GPIO_PIN_122, GPIO_PIN_123, GPIO_PIN_124, GPIO_PIN_125, GPIO_PIN_126, GPIO_PIN_127,

	GPIO_MAX_AMOUNT_OF_PINS
} GPIO_PinNumbers;

typedef enum
{
	GPIORC_FALSE = 0,
	GPIORC_TRUE = 1,
	GPIORC_LOW = 0,
	GPIORC_HIGH = 1,

	GPIORC_OK = 0,
	GPIORC_INVALID_PORT_HANDLE = -100,
	GPIORC_NOT_OUTPUT_PORT,
	GPIORC_NO_TIMER,
	GPIORC_NO_FREE_HANDLE,
	GPIORC_AMOUNT_OUT_OF_RANGE,
	GPIORC_INCORRECT_PORT_SIZE,
	GPIORC_PORT_NOT_ON_ONE_REG,
	GPIORC_INVALID_PIN_NUM,
	GPIORC_PIN_USED_IN_PORT,
	GPIORC_PIN_NOT_FREE,
	GPIORC_PIN_NOT_LOCKED,
	GPIORC_NULL_POINTER,
	GPIORC_PULLED_AND_OUTPUT,
	GPIORC_INCORRECT_PORT_TYPE,
	GPIORC_INCORRECT_TRANSITION_TYPE,
	GPIORC_INCORRECT_DEBOUNCE,
	GPIORC_INCORRECT_DIRECTION,
	GPIORC_INCORRECT_PULL,
	GPIORC_INCORRECT_INIT_VALUE,
	GPIORC_WRITE_TO_INPUT
} GPIOReturnCode;

typedef enum
{
	GPIO_IN_PIN = 0,
	GPIO_OUT_PIN = 1
} GPIOPinDirection;

typedef enum
{
	GPIO_PULL_DISABLE = 0,
	GPIO_PULLUP_ENABLE,
	GPIO_PULLDN_ENABLE
} GPIOPullType;

typedef enum
{
	GPIO_NO_EDGE = 0,
	GPIO_RISE_EDGE,
	GPIO_FALL_EDGE,
	GPIO_TWO_EDGE,
} GPIOTransitionType;

typedef struct
{
	GPIOPinDirection pinDir;
	UINT32 initLv;
	GPIOPullType pinPull;
	GPIOTransitionType pinEd;
	GPIOCallback isr;
	GPIOCallback wu;
} GPIOConfiguration;

/***********************************************************************
 *                                                                      *
 * Description: Writes a value to a port					               *
 *                                                                      *
 * Parameters:	portHandle - the port handle                           *
 *				value - the value to be written						   *
 *                                                                      *
 * Return value: GPIORC_OK		                                       *
 *				GPIORC_INVALID_PORT_HANDLE
 *				GPIORC_INCORRECT_INIT_VALUE
 *				GPIORC_WRITE_TO_INPUT								   *
 *                                                                      *
 * Notes:                                                               *
 ***********************************************************************/
GPIOReturnCode hal_GpioOut(UINT32 portHandle, UINT32 value);

/***********************************************************************
*			                                            			   *
* Description: Get current level of a port					           *
*                                                                      *
* Parameters:	portHandle - the port handle                           *
*										   							   *
*                                                                      *
* Return value: GPIORC_LOW
				GPIORC_HIGH  										   *
*				GPIORC_INVALID_PORT_HANDLE
*
*			                                            			   *
* Notes:                                                               *
***********************************************************************/
GPIOReturnCode hal_GpioIn(UINT32 portHandle);

/***********************************************************************
* 																	   *
* Description: Controls the direction of a given port                  *
*                                                                      *
* Parameters:	portHandle - the port handle                           *
*				dir - the required direction						   *
*                                                                      *
* Return value: GPIORC_OK		                                       *
*				GPIORC_INVALID_PORT_HANDLE						       *
*               GPIORC_INCORRECT_DIRECTION
				GPIORC_PIN_USED_IN_PORT							   *
*                                                                      *
* Notes:                                                               *
* 																	   *
*																	   *
* 																	   *
* If the port is with interrupt, it can not be changed to output with *
* this API																*
*************************************************************************/
GPIOReturnCode hal_GpioSetDir(UINT32 portHandle, GPIOPinDirection dir);

/***********************************************************************
* 																	   *
* Description: Get the direction of a given port                  	   *
*                                                                      *
* Parameters:	portHandle - the port handle                           *
*                                                                      *
* Return value: GPIO_IN_PIN
				GPIO_OUT_PIN										   *
*				GPIORC_INVALID_PORT_HANDLE						       *
*
*                                                                      *
* Notes:                                                               *
* 																	   *
**************************************************************************/
GPIOPinDirection hal_GpioGetDir(UINT32 portHandle);

/***********************************************************************
* 																	   *
* Description: Bind a callback function to a GPIO's wakeup event       *
*                                                                      *
* Parameters:	portHandle - the port handle                           *
*                                                                      *
* Return value: GPIORC_OK
				GPIO_NULL_POINTER 									   *
*				GPIORC_INVALID_PORT_HANDLE			                   *
* Notes:                                                               *
* 																	   *
**************************************************************************/
GPIOReturnCode hal_ConfigGpio(UINT32 portHandle, GPIOConfiguration config);

#endif
